/*
 * Copyright (C) 2011 Moritz Schmale <narrow.m@gmail.com>
 *
 * DropChest is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/gpl.html>.
 */

package me.scotty86.DropChest;


import java.util.Iterator;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.bukkit.CoalType;
import org.bukkit.DyeColor;
import org.bukkit.Material;
import org.bukkit.TreeSpecies;
import org.bukkit.inventory.ItemStack;
import org.bukkit.material.Coal;
import org.bukkit.material.Colorable;
import org.bukkit.material.MaterialData;
import org.bukkit.material.SpawnEgg;
import org.bukkit.material.TexturedMaterial;
import org.bukkit.material.Tree;

public class FilterItem {
	static public FilterItem allItem = new FilterItem("all");
	
	// typeID == -1 means ALL
	private int typeID;
	// if dataID is less than zero, only the metarialID matters
	private byte dataID;
	ItemStack ItemOfFilter;
	
	@SuppressWarnings("deprecation")
	public FilterItem(int typeID, byte dataID)
	{
		this.typeID = typeID;
		if(this.typeID > -1)
		{
			this.dataID = dataID;
			ItemOfFilter = new ItemStack(typeID, 1, (short) 0, (this.dataID > -1 ? this.dataID : 0));
		}
	}
	
	@SuppressWarnings("deprecation")
	public FilterItem(Material inMaterial)
	{
		this(inMaterial.getId(), (byte) -1);
	}
	
	@SuppressWarnings("deprecation")
	public FilterItem(MaterialData inMaterialData)
	{
		this(inMaterialData.getItemTypeId(), inMaterialData.getData());
	}
	
	@SuppressWarnings("deprecation")
	public FilterItem(String myInput)
	{
		int[] tmp = GetFilterItemFromString(myInput);
		if(tmp == null)
		{
			throw new IllegalArgumentException();
		}
		else
		{
			this.typeID = tmp[0];
			if(this.typeID < -1)
				throw new IllegalArgumentException();
			
			if(this.typeID > -1)
			{
				try
				{
					ItemStack testForLegalItem = new ItemStack(typeID);
					if(testForLegalItem.getType() == Material.AIR)
						throw new IllegalArgumentException();
				}
				catch (Exception e)
				{
					throw new IllegalArgumentException();
				}
				this.dataID = (byte) tmp[1];
				ItemOfFilter = new ItemStack(typeID, 1, (short) 0, (this.dataID > -1 ? this.dataID : 0));
			}
		}
	}
	
	public String toString()
	{
		if(this.typeID == -1)
			return "ALL";
					
		if(this.dataID > -1)
			return this.typeID+":"+this.dataID;
		else
			return String.valueOf(this.typeID);
	}
	
	public String getDisplayName()
	{
		if(this.typeID == -1)
			return "ALL";
		
		String myOutput = getNiceName(ItemOfFilter);
		if(myOutput != null)
			return myOutput;

		return ItemOfFilter.getItemMeta().hasDisplayName() ? ItemOfFilter.getItemMeta().getDisplayName() : ItemOfFilter.getType().toString();
	}
	
	public int getTypeID()
	{
		return this.typeID;
	}
	
	public int getDataID()
	{
		return dataID;
	}
	
	@SuppressWarnings("deprecation")
	static public int[] GetFilterItemFromString(String itemstring)
	{
		int[] myOutput = null;
		itemstring = itemstring.toUpperCase();
		
		if(itemstring.equals("ALL"))
		{
			myOutput = new int[2];
			myOutput[0] = -1;
			myOutput[1] = -1;
			return myOutput;
		}
		
		if(StringUtils.countMatches(itemstring, ":") == 1)
		{
			String[] subIDs = itemstring.split(":");
			
			
			int itemid = -1;
			try {
				itemid = Integer.valueOf(subIDs[0]);
			} catch (NumberFormatException e) {
				return null;
			}
			
			int itemdata = -1;
			try {
				itemdata = Integer.valueOf(subIDs[1]);
			} catch (NumberFormatException e) {
				return null;
			}
			
			if((itemid != -1) && (itemdata != -1))
			{
				try {
					myOutput = new int[2];
					myOutput[0] = itemid;
					myOutput[1] = itemdata;
					return myOutput;
				}
				catch (Exception e) {
					myOutput = null;
				}
			}
		}
		else
		{
			int itemid = -1;
			try {
				itemid = Integer.valueOf(itemstring);
				myOutput = new int[2];
				myOutput[0] = itemid;
				myOutput[1] = -1;
				return myOutput;
			} catch (NumberFormatException e) {
				myOutput = null;
			}
		}
		
		if(myOutput == null)
		{
			try
			{
				Material tmp = Material.getMaterial(itemstring);
				myOutput = new int[2];
				myOutput[0] = tmp.getId();
				myOutput[1] = -1;
				return myOutput;
			}
			catch (Exception e)
			{
				myOutput = null;
			}
		}
		
		return myOutput;
	}
	
	public boolean equals(int typeID, int dataID)
	{
		if(this.typeID == -1)
			return true;
		
		if(this.typeID != typeID)
			return false;
		
		if ((this.dataID > -1) && (this.dataID != dataID))
			return false;
		
		return true;
	}
	
	@SuppressWarnings("deprecation")
	public boolean equals(Material inMaterial)
	{
		if(this.typeID == -1)
			return true;
		
		if(this.typeID != inMaterial.getId())
			return false;
		
		return true;
	}
	
	@SuppressWarnings("deprecation")
	public boolean equals(MaterialData inMaterialData)
	{
		if(this.typeID == -1)
			return true;
		
		if(this.typeID != inMaterialData.getItemTypeId())
			return false;
		
		if ((this.dataID > -1) && (this.dataID != inMaterialData.getData()))
			return false;
		
		return true;
	}
	
	public boolean equals(FilterItem inFilterItem)
	{
		if(this.typeID != inFilterItem.getTypeID())
			return false;
		
		if(this.dataID != inFilterItem.getDataID())
			return false;
		
		return true;
	}
	
	public boolean isContained(List<FilterItem> FilterList)
	{
		for(FilterItem tmp : FilterList)
			if(this.equals(tmp))
				return true;
		return false;
	}
	
	public void removeFromList(List<FilterItem> FilterList)
	{
		for (Iterator<FilterItem> iterator = FilterList.iterator(); iterator.hasNext(); )
		{
			FilterItem tmpItem = iterator.next();
			if(this.equals(tmpItem))
			{
				iterator.remove();
				return;
			}
	    }
		return;
	}
	
	
	private static String getNiceName(ItemStack itemStack)
	{
		MaterialData data = itemStack.getData();
		
		if (data == null)
			return null;
		 
		if ((data instanceof TexturedMaterial))
			return ((TexturedMaterial)data).getMaterial().name();
		
		if ((data instanceof Colorable))
		{
			DyeColor color = ((Colorable)data).getColor();
			return color != null ? color.name() : null;
		}
		
		if ((data instanceof Tree))
		{
			TreeSpecies specie = ((Tree)data).getSpecies();
			return (specie != null) && (specie != TreeSpecies.GENERIC) ? specie.name() + "_" + itemStack.getType().toString() : null;
		}
		
		if ((data instanceof SpawnEgg))
		{
			org.bukkit.entity.EntityType type = ((SpawnEgg)data).getSpawnedType();
			return type != null ? type.name() : null;
		}
		
		if ((data instanceof Coal))
		{
			CoalType coal = ((Coal)data).getType();
			return (coal != null) && (coal != CoalType.COAL) ? coal.name() : null;
		}
		return null;
	}
	
}